题目来源:洛谷P1019 单词接龙
调了好几天,最后请教了醉神(@magolor),十分钟给我调好了…
这个程序一个问题就是循环根本就不会吧dict
全循环一遍,那可能就是初始化出了问题: m=pointer
的位置,当时记得应该写一个副本 m
代替 pointer
被改变,但是写着写着忘了 m
具体应该在哪被初始化了,问题就出现在这
回溯的状态:一定要明确回溯应当回溯到具体那个状态,是ans_temp
已经被改变的状态吗?还是未改变的状态?本题中是ans_temp
未改变的状态
我的解与标解
跟我的做法一样,区别只是标解用for
循环枚举j
而不是跟我一样用直接用dfs
函数
下面是我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 #include <iostream> #include <cstdio> #include <cmath> #include <cstring> using namespace std;char dict[21 ][30 ],ans[500 ]; int n,vis[21 ],ans_max=0 ,ans_temp=0 ;void dfs (int ,int ) ;int main () { cin>>n; for (int i=1 ;i<=n;i++) cin>>dict[i]; for (int i=1 ;i<=n;i++) vis[i]=2 ; cin>>dict[0 ][0 ]; dfs (0 ,0 ); cout<<ans_max; return 0 ; } void dfs (int word,int pointer) { if (pointer<strlen (dict[word])){ ans_temp++; int ans_mark=ans_temp; ans_max=max (ans_max,ans_temp); dfs (word,pointer+1 ); ans_temp=ans_mark; } int m; for (int i=1 ;i<=n;i++){ if (vis[i]>0 ){ int j=0 ; m=pointer; if (dict[word][m]==dict[i][j]){ bool flag=true ; while (m<strlen (dict[word])){ if (dict[word][m]!=dict[i][j]) flag=false ; m++; j++; } if (flag){ int ans_mark=ans_temp; ans_temp+=j-1 ; ans_max=max (ans_max,ans_temp); vis[i]--; dfs (i,j); vis[i]++; ans_temp=ans_mark; } } } } }
先预处理得到两两单词间的最短重合部分,然后搜索得到答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 #include <cstring> #include <iostream> #include <cstdio> using namespace std;string dict[31 ]; int ans_now=1 ,ans_max=0 ,n,vis[31 ],overlap[31 ][31 ]; int find_overlap (string,string) ;void dfs (int ) ;int main () { cin>>n; for (int i=1 ;i<=n;i++) cin>>dict[i]; for (int i=1 ;i<=n;i++) vis[i]=2 ; cin>>dict[0 ]; memset (overlap,0 ,sizeof (overlap)); for (int i=0 ;i<=n;i++) for (int j=1 ;j<=n;j++) overlap[i][j]=find_overlap (dict[i],dict[j]); dfs (0 ); cout<<ans_max; return 0 ; } int find_overlap (string a, string b) { for (int i=a.size ()-1 ;i>=0 ;i--){ int ja=i,jb=0 ; bool flag=true ; while (ja<a.size ()){ if (a[ja]!=b[jb]) {flag=false ; break ;} ja++; jb++; } if (flag){ int ans_overlap=a.size ()-i; if (ans_overlap!=a.size ()&&ans_overlap!=b.size ()) return ans_overlap; else if (a.size ()==1 ) return ans_overlap; else return 0 ; } } return 0 ; } void dfs (int word) { for (int i=1 ;i<=n;i++){ if (overlap[word][i]>0 && vis[i]>0 ){ ans_now+=dict[i].size ()-overlap[word][i]; ans_max=max (ans_max,ans_now); vis[i]--; dfs (i); vis[i]++; ans_now-=dict[i].size ()-overlap[word][i]; } } }